package com.googlecode.lazyrecords.chronicle;

import com.googlecode.lazyrecords.AbstractRecords;
import com.googlecode.lazyrecords.Definition;
import com.googlecode.lazyrecords.Keyword;
import com.googlecode.lazyrecords.Record;
import com.googlecode.lazyrecords.chronicle.mappings.ChronicleMapping;
import com.googlecode.lazyrecords.chronicle.mappings.ChronicleMappings;
import com.googlecode.totallylazy.Block;
import com.googlecode.totallylazy.Predicate;
import com.googlecode.totallylazy.Sequence;
import com.higherfrequencytrading.chronicle.Excerpt;
import com.higherfrequencytrading.chronicle.impl.IndexedChronicle;

import java.io.File;
import java.io.IOException;

import static com.googlecode.totallylazy.LazyException.lazyException;

public class ChronicleRecords extends AbstractRecords {

    private final File directory;
    private final ChronicleMappings mappings;

    public ChronicleRecords(File directory, ChronicleMappings mappings) {
        this.directory = directory;
        this.mappings = mappings;
    }

    @Override
    public Number add(Definition definition, Sequence<Record> records) {
        final IndexedChronicle chronicle = chronicleFor(definition);
        final Excerpt excerpt = chronicle.createExcerpt();
        for (Record record : records) {
            definition.fields().each(writeField(record, excerpt));
        }
        excerpt.finish();
        return records.size();
    }

    @Override
    public Number remove(Definition definition, Predicate<? super Record> predicate) {
        final Sequence<Record> toRemove = get(definition).filter(predicate);

    }

    @Override
    public Sequence<Record> get(Definition definition) {
        final IndexedChronicle chronicle = chronicleFor(definition);
        return new ChronicleSequence(definition, chronicle, mappings);
    }


    private Block<? super Keyword<?>> writeField(final Record record, final Excerpt excerpt) {
        return new Block<Keyword<?>>() {
            @Override
            protected void execute(Keyword<?> keyword) throws Exception {
                final Object value = record.get(keyword);
                final ChronicleMapping<Object> mapping = mappings.get(value.getClass());
                mapping.write(value, excerpt);
            }
        };
    }

    private IndexedChronicle chronicleFor(Definition definition) {
        try {
            return new IndexedChronicle(new File(directory, definition.name()).getAbsolutePath());
        } catch (IOException e) {
            throw lazyException(e);
        }
    }
}
